#!/usr/bin/env php
<?php
$SOAR_DIR=getenv("SOAR_DIR");
if(empty($SOAR_DIR)) $SOAR_DIR="/opt/soar";
include_once "$SOAR_DIR/common/php/soar/soar.inc";

function load_cnfg()
{/*{{{*/
    $svcenv_dir=getenv("SVCENV_DIR");
    if(empty($svcenv_dir))
    {
        print "Error: SVCENV_DIR not set\n";
        return false;
    }
    $svcenv_cnfg=getenv("SVCENV_CNFG");
    if(empty($svcenv_cnfg))
    {
        print "Error: SVCENV_CNFG not set\n";
        return false;
    }
    include $svcenv_cnfg;

    return true;
}/*}}}*/

class worker
{/*{{{*/
    public static $worker_idx=9999;

    private static $dbconn=array();

    public function get_dbconn($dbname)
    {/*{{{*/
        // get database passwd
        if(!array_key_exists($dbname, cnfg::$DB))
        {
            printf("Error: db(%s) not in cnfg\n", $dbname);
            return false;
        }
        if(array_key_exists($dbname, self::$dbconn))
            return self::$dbconn[$dbname];

        $dbcnfg=cnfg::$DB[$dbname];
        $passwd=svcnode_call::getdbpasswd(
                cnfg::$SVCNODE['PASSWD']['ADDR'],
                $dbname, $dbcnfg['USER']);
        if($passwd === false)
        {
            printf("Error: get db(%s) passwd fail\n", $dbname);
            return false;
        }

//        $dsn=sprintf("%s:host=%s;dbname=%s;charset=UTF-8",
//                $dbcnfg['TYPE'], $dbcnfg['HOST'], $dbcnfg['DATABASE']);
//        try
//        {
//            $conn=new PDO($dsn, $dbcnfg['USER'], $passwd);
//            $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//            printf("connect to db(%s)\n", $dbname);
//        }
//        catch(PDOException $e)
//        {
//            printf("Error: connect to db(%s) fail: %s\n",
//                    $dbname, $e->getMessage());
//            return false;
//        }
//        self::$dbconn[$dbname]=$conn;

        switch($dbcnfg['TYPE'])
        {
            case "mysql":
            {
                $conn=mysqli_init();
                $conn->options(MYSQLI_INIT_COMMAND, "set names utf8");
                if($conn->real_connect($dbcnfg['HOST'], $dbcnfg['USER'],
                            $passwd, $dbcnfg['DATABASE'], 0, null,
                             MYSQLI_CLIENT_FOUND_ROWS) == false)
                {
                    printf("Error: connect to db(%s) fail:%s\n",
                            $dbname, mysqli_connect_errno());
                    return false;
                }
                self::$dbconn[$dbname]=$conn;
                printf("connect to db(%s)\n", $dbname);
                break;
            }

            case "oracle":
            {
                if(isset($dbcnfg['DATABASE']))
                    $conn=oci_connect($dbcnfg['USER'], $passwd,
                            $dbcnfg['DATABASE']);
                else
                    $conn=oci_connect($dbcnfg['USER'], $passwd,
                            'localhost');
                if($conn === false)
                {
                    $error=oci_error();
                    printf("Error: connect to db(%s) fail:%d %s",
                            $dbname,
                            $error['code'], $error['message']);
                    return false;
                }
                self::$dbconn[$dbname]=$conn;
                printf("connect to db(%s)\n", $dbname);
                break;
            }

            case "mssql":
            {
                $conn=mssql_connect($dbcnfg['HOST'], $dbcnfg['USER'],
                        $passwd);
                if($conn === false)
                {
                    printf("Error: connect to db(%s) fail",
                            $dbname);
                    return false;
                }
                if(mssql_select_db($dbcnfg['DATABASE'], $conn) == false)
                {
                    printf("Error: select db(%s) fail",
                            $dbcnfg['DATABASE']);
                    return false;
                }
                self::$dbconn[$dbname]=$conn;
                printf("connect to db(%s)\n", $dbname);
                break;
            }

            default:
            {
                printf("Error: dababase not supported\n");
                $conn=false;
                break;
            }
        }

        return $conn;
    }/*}}}*/

    private function close_dbconn()
    {/*{{{*/
        foreach(self::$dbconn as $name=>$conn)
        {
            $dbcnfg=cnfg::$DB[$name];

//            self::$dbconn[$name]=null;
//            unset(self::$dbconn[$name]);

            switch($dbcnfg['TYPE'])
            {
                case "mysql":
                {
                    $conn->close();
                    unset(self::$dbconn[$name]);
                    printf("close db(%s)\n", $name);
                    break;
                }
                case "oracle":
                {
                    oci_close($conn);
                    unset(self::$dbconn[$name]);
                    printf("close db(%s)\n", $name);
                    break;
                }
                case "mssql":
                {
                    mssql_close($conn);
                    unset(self::$dbconn[$name]);
                    printf("close db(%s)\n", $name);
                    break;
                }
                default:
                {
                    break;
                }
            }
        }
    }/*}}}*/

    public function start($isfile, $svc, $request)
    {/*{{{*/
        print "Request:\n";
        print "$svc\n";
        print_r($request);
        print "----------------------------------------\n";

        print "Process:\n";
        if($isfile)
        {
            @include_once getenv("SVCENV_DIR")."/src/svc/svr.inc";
            @include_once getenv("SVCENV_DIR")."/src/svc/${svc}.inc";
            $func="SVC_FUNC_$svc";
            if(function_exists($func))
            {
                try
                {
                    $response=$func($request);
                    if($response === false)
                    {
                        $response=array('errcode'=>SOAR_ERR::DB);
                    }
                }
                catch(Exception $e)
                {
                    printf("Error: unhandled exception: %s\n",
                            $e->getMessage()); 
                    $response=array('errcode'=>SOAR_ERR::RESOURCE);
                }
            }
            else
            {
                printf("svc(%s) not found\n", $svc);
                $response=array('errcode'=>SOAR_ERR::SVC_NOT_FOUND);
            }
            self::close_dbconn();
        }
        else
        {
            $svcenv=new svcenv();
            $response=$svcenv->call($svc, $request);
            if($response === false)
            {
                echo "call svcenv fail\n";
                $svcenv->close();
                return 1;
            }
            $svcenv->close();
        }
        print "----------------------------------------\n";
  
        print "Response:\n";
        print_r($response);
        print "----------------------------------------\n";

        return true;
    }/*}}}*/
}/*}}}*/

function usage($selfname)
{/*{{{*/
    print "Usage: $selfname [-f] SERVICE [key:value ...]\n";
    print "Option -f: call service from src/svc directly, not from running SERVER\n";
    print "\n";
}/*}}}*/

function main($argv)
{/*{{{*/
    $selfname=basename(array_shift($argv));
    if(empty($argv))
    {
        usage($selfname);
        return 1;
    }

    $svc=array_shift($argv);
    if($svc == '-f')
    {
        if(empty($argv))
        {
            usage($selfname);
            return 1;
        }
        $svc=array_shift($argv);
        $isfile=true;
    }
    else
        $isfile=false;
    $svc=strtoupper($svc);

    $request=array();
    foreach($argv as $v)
    {
        $arr=split(':', $v);
        if($arr === false || count($arr) != 2)
        {
            print "para($v) invalid\n\n";
            usage($selfname);
            return 1;
        }
        $request[$arr[0]]=$arr[1];
    }

    if(load_cnfg() == false)
        return 1;
    if(worker::start($isfile, $svc, $request) == false)
        return 1;
    return 0;
}/*}}}*/

exit(main($argv));
?>
